#pragma once

#include <iostream>
#include <stdio.h>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

std::string gpath = "/home/wks/code/";
int gshmprojId = 0x6666;
//操作系统，申请空间，是按照块为单位的: 4KB ,1KB, 2KB, 4MB
int gshmsize = 4096;
mode_t gshmmode = 0600;

std::string ToHex(key_t key)
{
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "0x%x" ,key);

    return buffer;
}

class ShareMemory
{
private:
    void CreatHelper(int shmflg) 
    {
        _key = ::ftok(gpath.c_str(), gshmprojId);
        if (_key < 0)
        {
            std::cerr << "ftok error" << std::endl;
            return;
        }
        // std::cout << "_key: " << _key << std::endl;

        _shmid = ::shmget(_key, gshmsize, shmflg);
        if (_shmid < 0)
        {
            std::cerr << "shmget error" << std::endl;
            return;
        }
        std::cout << "shmid: " << _shmid << std::endl;
    }
public : 
    ShareMemory()
        :_shmid(-1), 
        _key(0),
        _addr(nullptr)
        {}
    
    void CreatShm()
    {
        if(_shmid == -1)
            CreatHelper(IPC_CREAT | IPC_EXCL | gshmmode);
    }

    void GetShm()
    {
        CreatHelper(IPC_CREAT);
    }

    void AttachShm()
    {
        _addr = shmat(_shmid, nullptr, 0);//为什么会失败？，因为没有加shmmode权限
        if((long long)_addr == -1)
        {
            std::cout<< "attach error" <<std::endl;
        }
    }

    void DetachShm()
    {
        if(_addr != nullptr)
            ::shmdt(_addr);

        std::cout<< "dattach done" <<std::endl;
    }

    void DeleteShm()
    {
        ::shmctl(_shmid, IPC_RMID, nullptr);
    }

    void* GetAddr()
    {
        return _addr;
    }

    void ShmData()
    {
        struct shmid_ds buffer; //系统提供的数据类型
        int n = ::shmctl(_shmid, IPC_STAT, &buffer);
        if(n < 0) return ;
        std::cout<< "#####################"<<std::endl;
        std::cout<< buffer.shm_atime <<std::endl;
        std::cout<< buffer.shm_cpid << std::endl;
        std::cout<< buffer.shm_ctime <<std::endl;
        std::cout<< buffer.shm_nattch <<std::endl;
        std::cout<< ToHex(buffer.shm_perm.__key) <<std::endl;
        std::cout<< "#####################"<<std::endl;
    }

    ~ShareMemory()
    {}

private:
    key_t _key;
    int _shmid;
    void* _addr;
};

ShareMemory shm;

struct data//sum=4096
{
    char status[32];
    char lasttime[48];
    char image[4000];
};